package com.AdvancedDemos.FileAndIO;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Scanner;
import java.util.function.BiConsumer;

public class 练习1 {

    /**
     * 1.键盘录入一个只包含数字和字母的字符串,并将字符串存储在当前模块下的
     * message.txt
     * 2.读取message.txt中的内容,统计其中每个字符出现的次数,
     * 并将统计结果存储在当前模块下的result.txt中
     * 格式:
     * 输入:aaabbbddccc
     * 结果:
     * a=3
     * b=3
     * c=3
     * d=2
     */
    public static void main(String[] args) {
        /**
         *1.键盘录入一个只包含"数字"和"字母"的字符串,并将字符串存储在当前模块下的message.txt中*/
        //读取字符串,并判断时候合法,不合法就一直输入,直到合法为止
        String str = null;
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入一个字符串,只包含\"数字\"和\"字母\":");
            str = sc.nextLine();
            int i;
            for (i = 0; i < str.length(); i++) {
                char c = str.charAt(i);
                if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) {
                    //表示c不是数字或者字母
                    System.out.println("你输入了非数字非字母字符,请重输!");
                    break;//结束for循环
                }
            }
            if (i == str.length()) {
                //说明此时所有字符都是合法的,是数字或者字母
                break;//结束while(true){}
            }
        }
        System.out.println("str的内容是:" + str);//此时str一定已经合法,只含有数字和字母

        //将字符串存储在当前模块下的message.txt中
        //我当前.java文件所在的相对(项目根目录的)路径是helloworld\src\com\AdvancedDemos\FileAndIO
        FileOutputStream fileOutputStream = null;
        try {
            //创建文件
            fileOutputStream = new FileOutputStream("helloworld\\src\\com\\AdvancedDemos\\FileAndIO\\message.txt");//此处不给append参数,默认追加模式是false的,多给一个true会打开追加模式;追加模式关闭时不会在原文件内容末尾追加新内容,而是删除原文件再创建新文件,从第一个字节开始重新写
            //将str写入message.txt
            fileOutputStream.write(str.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        /**
         *2.读取message.txt中的内容,统计其中每个字符出现的次数*/
        FileInputStream fileInputStream = null;
        String result = "";
        try {
            //打开文件
            //文件相对项目根目录的相对路径是helloworld\src\com\AdvancedDemos\FileAndIO\message.txt
            fileInputStream = new FileInputStream("helloworld\\src\\com\\AdvancedDemos\\FileAndIO\\message.txt");
            //从message.txt读取,存储到一个字符串中
            byte[] bytes = new byte[5];//每次最多读取5个字节
            int count;//表示当次实际读取的字节数
            while ((count = fileInputStream.read(bytes)) != -1) {
                //表示本次有读到文件内容
                result += new String(bytes, 0, count);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("result的内容是:" + result);
        //统计字符串result中每个字符出现的次数(显然要使用到HashMap键值对的形式来表示某个字符与其出现的次数之间的联系)
        HashMap<Character, Integer> map = new HashMap<>();
        char[] chars = result.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (map.containsKey(chars[i])) {
                //表示该字符已经统计过至少一次了
                map.put(chars[i], map.get(chars[i]) + 1);
            } else {
                //表示该字符是第一次统计
                map.put(chars[i], 1);
            }
        }


        /**将统计结果存储在当前模块下的result.txt中
         *格式:
         *输入:aaabbbddccc
         *结果:
         *a=3
         *b=3
         *c=3
         *d=2
         */
        //打印统计结果,并按格式要求存入到result.txt中
        System.out.println("统计结果是:");
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("helloworld\\src\\com\\AdvancedDemos\\FileAndIO\\result.txt");//此处没有把创建文件的操作放到下面map.forEach的循环中,避免了多次重复打开关闭
            FileOutputStream finalFos = fos;//是为了解决变量 'fos' 从内部类中访问，需要为 final 或有效 final的问题
            map.forEach(new BiConsumer<Character, Integer>() {
                @Override
                public void accept(Character key, Integer value) {
                    String temp = key + "=" + value;
                    System.out.println(temp);
                    try {//因为在匿名内部类中似乎外面的try catch对里面不可见,不在这里try catch的话write会报错
                        finalFos.write(temp.getBytes());
                        finalFos.write("\r\n".getBytes());//写出换行符
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        /**
         * 运行结果:
         * 请输入一个字符串,只包含"数字"和"字母":
         * 12 3as
         * 你输入了非数字非字母字符,请重输!
         * 请输入一个字符串,只包含"数字"和"字母":
         * !dsjl2
         * 你输入了非数字非字母字符,请重输!
         * 请输入一个字符串,只包含"数字"和"字母":
         * 123abc321bca
         * str的内容是:123abc321bca
         * result的内容是:123abc321bca
         * 统计结果是:
         * 1=2
         * a=2
         * 2=2
         * b=2
         * 3=2
         * c=2
         */

    }
}